package org.teremail.store;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Random;

import org.junit.Before;
import org.junit.Test;


public abstract class AbstractStoreTestCase {

    private Store store;

    protected abstract Store getStore();
    protected void onSetup() throws Exception {}
    
    @Before
    public void setUp() throws Exception {
        onSetup();
        this.store = getStore();
    }
    

    @Test
    public void create() {
        
        String id = store.createStoreItem();
        
        assertNotNull(id);
    }
    
    
    private void readWrite(int dataSize) throws IOException {
        byte[] data = new byte[dataSize];
        Random r = new Random(1L);
        r.nextBytes(data);
        
        String id = store.createStoreItem();
        
        OutputStream out = store.getOutputStream(id);
        out.write(data);
        out.flush();
        
        InputStream in = store.getInputStream(id);
        byte[] result = new byte[dataSize];
        in.read(result);
        
        assertTrue(Arrays.equals(data, result));
    }
    
    private void readWrite(int dataSize, int count) throws IOException {
        byte[] data = new byte[dataSize];
        Random r = new Random(1L);
        r.nextBytes(data);
        
        String id = store.createStoreItem();
        
        OutputStream out = store.getOutputStream(id);
        for (int i = 0; i < count; i++) {
            out.write(data);
        }
        out.flush();
        
        InputStream in = store.getInputStream(id);
        byte[] result = new byte[dataSize];
        for (int i = 0; i < count; i++) {
            in.read(result);
            assertTrue(Arrays.equals(data, result));
        }
        
    }
    
    @Test
    public void writeAndRead_1B() throws IOException {
        readWrite(1);
    }
    
    @Test
    public void writeAndRead_1K() throws IOException {
        readWrite(1024);
    }
    
    @Test
    public void writeAndRead_10K() throws IOException {
        readWrite(1024 * 10);
    }
    
    @Test
    public void writeAndRead_537B_1() throws IOException {
        readWrite(537, 1);
    }
    
    @Test
    public void writeAndRead_537B_2() throws IOException {
        readWrite(537, 2);
    }
    
    @Test
    public void writeAndRead_537B_7() throws IOException {
        readWrite(537, 7);
    }
}
